package com.example.cartservice.config;

import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.cartservice.utils.Result;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

/**
 * 全局异常处理配置类
 * 用于统一处理控制器层抛出的异常并返回标准化响应
 *
 * @author czwa
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理文件上传大小超出限制的异常
     * 当上传文件大小超过配置的最大值时触发
     *
     * @param e 异常对象
     * @param request HTTP请求对象
     * @return 包含错误信息的Result对象，文件下载请求返回null
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public Result handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e, HttpServletRequest request) {
        // 检查是否为文件下载请求，若是则不返回JSON响应
        if (isFileDownloadRequest(request)) {
            return null; // 让Spring Boot继续处理原始响应
        }
        return Result.error("文件大小超出限制1.0MB");
    }

    /**
     * 处理Sentinel流控/熔断降级异常
     * 当触发Sentinel的流量控制或服务降级时触发
     *
     * @param e 异常对象
     * @param request HTTP请求对象
     * @return 包含降级提示的Result对象，文件下载请求返回null
     */
    @ExceptionHandler(BlockException.class)
    public Result handleSentinelBlockException(BlockException e, HttpServletRequest request) {
        if (isFileDownloadRequest(request)) return null;
        // 返回自定义的降级响应
        return Result.error("系统繁忙，请稍后再试 (Sentinel Fallback)");
    }

    /**
     * 处理未被具体异常处理器捕获的通用异常
     * 作为异常处理的最后一道防线
     *
     * @param e 异常对象
     * @param request HTTP请求对象
     * @return 包含异常信息的Result对象，文件下载请求返回null
     */
    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e, HttpServletRequest request) {
        if (isFileDownloadRequest(request)) {
            return null;
        }
        return Result.error(e.getMessage());
    }

    /**
     * 判断是否为文件下载请求
     * 通过请求的Content-Type字段进行判断
     *
     * @param request HTTP请求对象
     * @return true表示文件下载请求，false表示普通请求
     */
    private boolean isFileDownloadRequest(HttpServletRequest request) {
        String contentType = request.getContentType();
        // 示例判断：Content-Type以Excel文件格式开头
        return contentType != null && contentType.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    }
}